/**
 * author      : dormi330
 * date        : 2018/6/24
 * project     : mybatis
 * description : 领域行为: 创建订单
 */

package com.deep.trade.domain.order;

import com.deep.trade.adaptor.required.IdService;
import com.deep.trade.adaptor.required.MemberAddress;
import com.deep.trade.adaptor.required.logistical.LogisticalService;
import com.deep.trade.adaptor.required.member.Member;
import com.deep.trade.adaptor.required.sku.ItemSkuService;
import com.deep.trade.adaptor.required.sku.Sku;
import com.deep.trade.common.TradeException;
import com.deep.trade.order.SkuAndQty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommandPlaceOrder {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private IdService idService;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ItemSkuService itemSkuService;

    @Autowired
    private LogisticalService logisticalService;

    /**
     * 新建订单
     *
     * @param tenantCode    租户code
     * @param member        会员
     * @param address       地址
     * @param skuAndQtyList
     * @throws Exception
     */
    @Transactional
    public void placeOrder(
            String tenantCode,
            Member member,
            MemberAddress address,
            String remark,
            List<SkuAndQty> skuAndQtyList) throws Exception {

        List<TradeOrderSku> tradeOrderSkuList = tradeOrderSkuSetup(tenantCode, skuAndQtyList, member, address);

        // 拆单得到多个 TradeOrder 和 DeliveryAddress
        Map<String, TradeOrder> tradeOrderMap = new HashMap<>();
        Map<String, DeliveryAddress> orderDeliveryMap = new HashMap<>();

        for (TradeOrderSku tradeOrderSku : tradeOrderSkuList) {
            // tradeOrder
            String shopId = tradeOrderSku.getShopId();
            TradeOrder tradeOrder = tradeOrderMap.get(shopId);
            if (tradeOrder == null) {
                tradeOrder = tradeOrderFromSku(tradeOrderSku, member, remark);
                tradeOrderMap.put(shopId, tradeOrder);
            }
            tradeOrder.addTradeOrderSku(tradeOrderSku);

            // 地址信息
            if (null == orderDeliveryMap.get(shopId)) {
                DeliveryAddress deliveryAddress = splitOrderOfOrderDelivery(tenantCode, member.getId(), tradeOrder.getId(), address);
                orderDeliveryMap.put(shopId, deliveryAddress);
            }
        }

        for (TradeOrder tradeOrder : tradeOrderMap.values()) {
            tradeOrder.calculateMoney();
        }
        // 创建 一个 OrderSummary
        OrderSummary orderSummary = createOrderSummary(tenantCode, member);
        for (TradeOrder tradeOrder : tradeOrderMap.values()) {
            orderSummary.addTradeOrder(tradeOrder);
        }
        orderSummary.calculateMoney();

        // 进行存储
        peresistNewOrder(orderSummary, tradeOrderMap.values(), orderDeliveryMap.values(), tradeOrderSkuList);

        // TODO 订单创建之后, 如果有支付超时限制, 则启动
    }

    private TradeOrder tradeOrderFromSku(TradeOrderSku tradeOrderSku, Member member, String remark) {
        TradeOrder tradeOrder = new TradeOrder();
        tradeOrder.setId(idService.uuid());
        tradeOrder.setTenantCode(tradeOrderSku.getTenantCode());
        tradeOrder.setCreatedBy(member.getId());
        tradeOrder.setUpdatedBy(member.getId());

        // orderSummaryId
        // orderType        暂不需要
        // orderChannel     暂不需要
        // code             暂不需要
        tradeOrder.setSellerId(tradeOrderSku.getSellerId());
        tradeOrder.setSellerName(tradeOrderSku.getSellerName());
        tradeOrder.setShopId(tradeOrderSku.getShopId());
        tradeOrder.setMemberId(member.getId());
        tradeOrder.setMemberName(member.getName());
        tradeOrder.setRemark(remark);
        // sellerRemark     暂不需要
        tradeOrder.setStatus(TradeOrder.STATUS_TO_BE_AUDITED);
        tradeOrder.setDiscountMoney(BigDecimal.ZERO);

        return tradeOrder;
    }


    private void peresistNewOrder(
            OrderSummary orderSummary,
            Collection<TradeOrder> tradeOrderList,
            Collection<DeliveryAddress> deliveryAddressList,
            Collection<TradeOrderSku> tradeOrderSkuList) throws Exception {

        orderRepository.addOrderSummary(orderSummary);

        for (TradeOrder tradeOrder : tradeOrderList) {
            orderRepository.addTradeOrder(tradeOrder);
        }

        for (DeliveryAddress deliveryAddress : deliveryAddressList) {
            orderRepository.addOrderDelivery(deliveryAddress);
        }

        for (TradeOrderSku tradeOrderSku : tradeOrderSkuList) {
            orderRepository.addOrderSku(tradeOrderSku);
        }
    }

    private OrderSummary createOrderSummary(String tenantCode, Member member) {
        OrderSummary orderSummary = new OrderSummary();
        orderSummary.setId(idService.uuid());
        orderSummary.setTenantCode(tenantCode);
        orderSummary.setCreatedBy(member.getId());
        orderSummary.setUpdatedBy(member.getId());
        orderSummary.setMemberId(member.getId());
        orderSummary.setMemberName(member.getName());

        orderSummary.setPlatformDiscountMoney(platformDiscount());

        return orderSummary;
    }

    // 计算平台折扣, 这部分逻辑暂时没有
    private BigDecimal platformDiscount() {
        return BigDecimal.ZERO;
    }

    // 拆单之 创建OrderDelivery
    private DeliveryAddress splitOrderOfOrderDelivery(
            String tenantCode,
            String memberId,
            String tradeOrderId,
            MemberAddress address) {
        DeliveryAddress deliveryAddress = new DeliveryAddress();
        deliveryAddress.setId(idService.uuid());
        deliveryAddress.setTenantCode(tenantCode);
        deliveryAddress.setCreatedBy(memberId);
        deliveryAddress.setUpdatedBy(memberId);
        deliveryAddress.setTradeOrderId(tradeOrderId);

        deliveryAddress.setProvinceName(address.getProviceName());
        deliveryAddress.setCityName(address.getCityName());
        deliveryAddress.setDistrictName(address.getDistrictName());
        deliveryAddress.setStreetName(address.getStreetName());
        deliveryAddress.setPostcode(address.getPostCode());
        deliveryAddress.setReceiverName(address.getReceiverName());
        deliveryAddress.setRecieverPhone(address.getReceiverPhone());
        deliveryAddress.setDetailAddr(address.getDetailAddress());
        return deliveryAddress;
    }


    /**
     * 组装 商品详情 数据接口
     *
     * @param skuAndQtyList
     * @return
     * @throws Exception
     */
    private List<TradeOrderSku> tradeOrderSkuSetup(
            String tenantCode,
            List<SkuAndQty> skuAndQtyList,
            Member member,
            MemberAddress address) throws Exception {
        if (null == skuAndQtyList || skuAndQtyList.size() == 0) throw new TradeException("no item");

        List<Sku> skuList = itemSkuService.skuOfIds(tenantCode,
                skuAndQtyList.stream()
                        .map(skuAndQty -> skuAndQty.getSkuId())
                        .collect(Collectors.toList()));

        if (skuList.size() != skuAndQtyList.size()) {
            throw new TradeException("some item not exist");
        }

        final Map<String, Sku> skuIdVsSku = new HashMap<>();
        skuList.stream().forEach(sku -> skuIdVsSku.put(sku.getId(), sku));

        List<TradeOrderSku> orderSkuArrayList = new ArrayList<>(skuAndQtyList.size());
        for (SkuAndQty skuAndQty : skuAndQtyList) {
            // Sku skuFromItem = itemSkuService.skuOfId(tenantCode, skuAndQty.getSkuId());        // 一次查询多个
            Sku skuFromItem = skuIdVsSku.get(skuAndQty.getSkuId());
            if (skuFromItem == null) throw new TradeException("item not exist, skuId=" + skuAndQty.getSkuId());

            int quantity = skuAndQty.getQuantity();
            if (quantity <= 0) throw new TradeException("item quantity illegal, quantity=" + quantity);

            // 计算价格
            BigDecimal freight = freightOfEachSku(skuFromItem.getId(), quantity, address);

            TradeOrderSku tradeOrderSku = new TradeOrderSku();
            tradeOrderSku.setTenantCode(tenantCode);
            tradeOrderSku.setCreatedBy(member.getId());
            tradeOrderSku.setUpdatedBy(member.getId());
            tradeOrderSku.setId(idService.uuid());
            tradeOrderSku.setSellerId(skuFromItem.getSellerId());
            tradeOrderSku.setSellerName(skuFromItem.getSellerName());
            tradeOrderSku.setShopId(skuFromItem.getShopId());
            tradeOrderSku.setItemId(skuFromItem.getShopId());
            tradeOrderSku.setItemName(skuFromItem.getItemName());
            tradeOrderSku.setSkuId(skuFromItem.getId());
            tradeOrderSku.setSkuCode(skuFromItem.getSkuCode());
            tradeOrderSku.setImgUrl(skuFromItem.getImgUrl());

            tradeOrderSku.setBrandId(skuFromItem.getBrandId());
            tradeOrderSku.setQuantity(quantity);
            // money
            tradeOrderSku.setDiscountMoney(BigDecimal.ZERO);
            tradeOrderSku.setPriceMoney(skuFromItem.getPrice());
            tradeOrderSku.setFreightMoney(freight);
            //
            tradeOrderSku.calculateMoney();

            //
            orderSkuArrayList.add(tradeOrderSku);
        }
        return orderSkuArrayList;
    }

    /**
     * 计算运费
     */
    private BigDecimal freightOfEachSku(String skuId, int quanlity, MemberAddress address) throws Exception {
        return logisticalService.freightOfSku(skuId, quanlity, address);
    }
}
